package pl.edu.wsinf.lukaszwalczak.emailclient.view;

import java.util.ArrayList;
import java.util.List;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.ToolBar;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.converter.DefaultStringConverter;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import pl.edu.wsinf.lukaszwalczak.emailclient.EmailClient;
import pl.edu.wsinf.lukaszwalczak.emailclient.controller.TaskController;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Task;

@Component
public class TaskView {

    @Inject
    private TaskController taskController;
    private Stage stage = null;
    private TableView<ObservableTask> table;
    private ToolBar toolbar;

    public void show() {
        if (stage == null) {
            stage = new Stage();

            //resizable disabled
            stage.setResizable(false);
            //create root node of scene, i.e. group
            BorderPane root = new BorderPane();
            //create scene with set width, height and color
            Scene scene = new Scene(root, 600, 340, Color.WHITESMOKE);
            scene.getStylesheets().add(EmailClient.class.getResource("/css/stylesheet.css").toExternalForm());
            //set scene to stage
            stage.setScene(scene);
            stage.setTitle("Zadania");
            //center stage on screen
            stage.centerOnScreen();

            toolbar = new ToolBar();

            Label labelField = new Label("Zadanie: ");
            toolbar.getItems().add(labelField);
            final TextField taskField = new TextField();
            taskField.setPrefWidth(350);
            toolbar.getItems().add(taskField);

            Button newAddTaskButton = ViewHelper.createButton("Dodaj", new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    taskController.createTask(taskField.getText());
                    taskField.setText("");
                    reloadList();
                }
            }, "plus.png", null, 30d);
            toolbar.getItems().add(newAddTaskButton);

            Button newDeleteTaskButton = ViewHelper.createButton("Usuń", new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    ObservableTask selected = table.getSelectionModel().getSelectedItem();
                    if (selected != null) {
                        taskController.removeTask(selected.getTask());
                    }
                    reloadList();
                }
            }, "minus.gif", null, 30d);
            toolbar.getItems().add(newDeleteTaskButton);
            root.setTop(toolbar);

            // Lista zadan
            table = new TableView<>();
            root.setCenter(table);

            TableColumn<ObservableTask, Boolean> doneColumn = new TableColumn<>();
            doneColumn.setCellValueFactory(new PropertyValueFactory<ObservableTask, Boolean>("done"));
            doneColumn.setCellFactory(CheckBoxTableCell.forTableColumn(doneColumn));
            doneColumn.setEditable(true);
            doneColumn.setMinWidth(40);
            doneColumn.setMaxWidth(40);
            table.getColumns().add(doneColumn);

            TableColumn<ObservableTask, String> descColumn = new TableColumn<>("Zadanie");
            descColumn.setMinWidth(250);
            descColumn.setCellValueFactory(new PropertyValueFactory<ObservableTask, String>("description"));
            descColumn.setCellFactory(TextFieldTableCell.<ObservableTask, String>forTableColumn(new DefaultStringConverter()));
            descColumn.setEditable(true);
            table.getColumns().add(descColumn);

            //Enabling editing
            table.setEditable(true);
            table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            reloadList();

            stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>() {
                @Override
                public void handle(WindowEvent t) {
                    markDone();
                }
            });

            //show the stage
            stage.show();

        } else {
            stage.show();
        }
    }

    private void markDone() {
        int i = 0;
        for (Node n : table.lookupAll("TableRow")) {
            if (n instanceof TableRow) {
                TableRow row = (TableRow) n;
                ObservableTask item = (ObservableTask) table.getItems().get(i);
                if (item.done.get()) {
                    row.getStyleClass().add("task-done-mark");
                } else {
                    row.getStyleClass().remove("task-done-mark");
                }
                i++;
                if (i == table.getItems().size()) {
                    break;
                }
            }
        }
    }

    public void reloadList() {
        List<Task> tasks = taskController.getTasks();
        table.setItems(FXCollections.<ObservableTask>observableList(convertToObservable(tasks)));
        markDone();
    }

    private List<ObservableTask> convertToObservable(List<Task> tasks) {
        List<ObservableTask> result = new ArrayList<>();
        for (Task task : tasks) {
            result.add(new ObservableTask(task));
        }
        return result;
    }

    public class ObservableTask {

        private Task task;
        private StringProperty description;
        private BooleanProperty done;

        public ObservableTask(Task task) {
            final Long id = task.getId();
            this.task = task;
            this.done = new SimpleBooleanProperty(task.isDone());
            this.description = new SimpleStringProperty(task.getDescription());

            this.description.addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> ov, String t, String t1) {
                    taskController.updateDescription(id, t1);
                }
            });

            this.done.addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                    taskController.updateDone(id, t1);
                    reloadList();
                }
            });
        }

        public StringProperty descriptionProperty() {
            return description;
        }

        public BooleanProperty doneProperty() {
            return done;
        }

        public Task getTask() {
            return task;
        }
    }
}
